import { BasePageResponseDto, BaseSingleResponseDto } from "../dtos/BaseDto";
import { Service } from "typedi";
import { Repository } from "typeorm";
import { InjectRepository } from "typeorm-typedi-extensions";
import { transformResponseDto } from "../utils/transform";
import { Role } from "../entity/Role";
import { CreateRoleDto, RoleDto, UpdateRoleDto } from "../dtos/RoleDto";

@Service()
export class RoleService {
  @InjectRepository(Role)
  private roleRepo!: Repository<Role>;

  public async findAll(): Promise<BasePageResponseDto<RoleDto>> {
    const pageIndex = 1;
    const pageSize = 2;
    const [roles, count] = await this.roleRepo.createQueryBuilder('role')
      .skip((pageIndex - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();
    const roleDtos = roles.map(item => {
      return this.transformEntity2Dto(item);
    })
    return {
      success: true,
      message: 'Get roles',
      data: roleDtos,
      total: count,
      pageIndex,
      pageSize,
    };
  }

  public async get(id: number, message = 'get role success'): Promise<BaseSingleResponseDto<RoleDto>> {
    const role = await this.roleRepo.findOne({ where: { id } });
    if (!role) {
      throw new Error('role not found');
    }
    const resRole = this.transformEntity2Dto(role!);
    return {
      success: true,
      message: message,
      data: resRole,
    }
  }

  public async create(role: CreateRoleDto): Promise<BaseSingleResponseDto<RoleDto>> {
    const newRole = this.roleRepo.create({
      name: role.name,
      description: role.description,
    });
    await this.roleRepo.save(newRole);
    const resRole = this.transformEntity2Dto(newRole);
    return {
      success: true,
      message: 'Role created',
      data: resRole,
    };
  }

  public async update(role: UpdateRoleDto): Promise<BaseSingleResponseDto<RoleDto>> {
    const oldRole = await this.roleRepo.findOne({ where: { id: role.id } });
    if (!oldRole) {
      throw new Error('Role not found');
    }
    const newRole = await this.roleRepo.update(role.id, {
      name: role.name,
      description: role.description,
    });
    if (!newRole.affected) {
      throw new Error('update error');
    }
    return this.get(role.id, 'update success');
  }

  public async batchDelete(roleIds: number[]): Promise<BaseSingleResponseDto<boolean>> {
    const result = await this.roleRepo.delete(roleIds);
    if (!result.affected) {
      throw new Error('delete error');
    }
    return {
      success: true,
      message: 'delete success',
      data: true,
    }
  }

  private transformEntity2Dto(entity: Role): RoleDto {
    return transformResponseDto<RoleDto, Role>(entity, {
      name: entity.name,
      description: entity.description,
    });
  }
}
